package com.ljb.android.comm.img

import android.annotation.SuppressLint
import android.content.Context
import android.graphics.Bitmap
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.graphics.drawable.Drawable
import android.text.TextUtils
import android.widget.ImageView
import androidx.annotation.DrawableRes
import androidx.fragment.app.Fragment
import com.bumptech.glide.Glide
import com.bumptech.glide.RequestManager
import com.bumptech.glide.request.RequestOptions
import com.bumptech.glide.request.target.SimpleTarget
import com.bumptech.glide.request.transition.Transition
import com.ljb.android.comm.img.core.*
import com.ljb.android.comm.utils.XLog

/**
 * 图片加载工具
 * @date 2021.09.01
 * @author ljb
 * */
class ImgLoader private constructor(var builder: Builder) {

    companion object;

    private var mUrl: String? = null
    private var mResId: Int = 0

    private var mImageView: ImageView? = null
    private var mBitmapListener: BitmapListener? = null

    private var mContext: Context? = null
    private var mFragment: Fragment? = null

    private var mFormat: ImgFormat
    private var mScaleType: ImgScaleType

    private var mPreDrawable: Drawable
    private var mErrorDrawable: Drawable

    init {
        mContext = builder.getContext()
        mFragment = builder.getFragment()
        mFormat = builder.getFormat()!!
        mScaleType = builder.getScaleType()!!
        mPreDrawable = builder.getPreview()!!
        mErrorDrawable = builder.getErrorView()!!
    }

    // 加载远程地址
    fun load(url: String, view: ImageView) {
        mImageView = view
        mUrl = url
        loadNext()
    }

    // 加载项目资源
    fun load(@DrawableRes resId: Int, view: ImageView) {
        mImageView = view
        mResId = resId
        loadNext()
    }

    // 远程资源转换为bitmap
    fun load(url: String, listener: BitmapListener) {
        mBitmapListener = listener
        mUrl = url
        loadNext()
    }

    // 项目资源转换为bitmap
    fun load(@DrawableRes resId: Int, listener: BitmapListener) {
        mBitmapListener = listener
        mResId = resId
        loadNext()
    }

    @SuppressLint("CheckResult")
    private fun loadNext() {
        val options = foundOptions(mFormat, mScaleType)
        options.placeholder(mPreDrawable)
        options.error(mErrorDrawable)

        mImageView?.run {
            load2ImageView(this, options)
            return@loadNext
        }

        mBitmapListener?.run {
            load2BitmapListener(this, options)
            return@loadNext
        }
    }

    /**
     * 构造器
     * */
    class Builder {

        private var mContext: Context? = null
        private var mFragment: Fragment? = null

        private var mFormat: ImgFormat? = null
        private var mScaleType: ImgScaleType? = null

        // 默认素材
        private var mDefColorId: Int = Color.parseColor("#f8f8f8")
        private var mPreDrawable: Drawable? = null
        private var mErrorDrawable: Drawable? = null

        fun getContext(): Context? {
            return mContext
        }

        fun getFragment(): Fragment? {
            return mFragment
        }

        fun getFormat(): ImgFormat? {
            return mFormat
        }

        fun getScaleType(): ImgScaleType? {
            return mScaleType
        }

        fun getPreview(): Drawable? {
            return mPreDrawable
        }

        fun getErrorView(): Drawable? {
            return mErrorDrawable
        }

        constructor(context: Context) {
            mContext = context
        }

        constructor(fragment: Fragment) {
            mFragment = fragment
        }

        fun preview(drawable: Drawable): Builder {
            mPreDrawable = drawable
            return this
        }

        @SuppressLint("UseCompatLoadingForDrawables")
        fun preview(@DrawableRes resId: Int): Builder {
            val context = mContext ?: mFragment?.context
            context?.run {
                mPreDrawable = context.resources.getDrawable(resId)
            }
            return this
        }

        fun error(drawable: Drawable): Builder {
            mErrorDrawable = drawable
            return this
        }

        @SuppressLint("UseCompatLoadingForDrawables")
        fun error(@DrawableRes resId: Int): Builder {
            val context = mContext ?: mFragment?.context
            context?.run {
                mErrorDrawable = context.resources.getDrawable(resId)
            }
            return this
        }

        fun format(format: ImgFormat): Builder {
            mFormat = format
            return this
        }

        fun scaleType(scaleType: ImgScaleType): Builder {
            mScaleType = scaleType
            return this
        }

        fun build(): ImgLoader {
            if (mPreDrawable == null) {
                mPreDrawable = ColorDrawable(mDefColorId)
            }

            if (mErrorDrawable == null) {
                mErrorDrawable = ColorDrawable(mDefColorId)
            }

            if (mFormat == null) {
                mFormat = ImgFormat.Default
            }

            if (mScaleType == null) {
                mScaleType = ImgScaleType.CenterInside
            }
            return ImgLoader(this)
        }
    }

    private fun load2ImageView(imageView: ImageView, options: RequestOptions) {
        mContext?.run {
            glideLoad(Glide.with(this), options, imageView)
            return@load2ImageView
        }

        mFragment?.run {
            glideLoad(Glide.with(this), options, imageView)
            return@load2ImageView
        }
    }

    private fun load2BitmapListener(listener: BitmapListener, options: RequestOptions) {
        mContext?.run {
            glideLoad(Glide.with(this), options, listener)
            return@load2BitmapListener
        }

        mFragment?.run {
            glideLoad(Glide.with(this), options, listener)
            return@load2BitmapListener
        }
    }

    @SuppressLint("CheckResult")
    private fun glideLoad(
        glideReq: RequestManager,
        options: RequestOptions,
        listener: BitmapListener
    ) {
        val bitmapReq = glideReq.asBitmap()
        when {
            !TextUtils.isEmpty(mUrl) -> {
                bitmapReq.load(mUrl)
            }
            mResId != 0 -> {
                bitmapReq.load(mResId)
            }
            else -> {
                XLog.e("ImgLoader : img url and resId is null")
                return
            }
        }.apply(options)
            .into(object : SimpleTarget<Bitmap>() {

                override fun onLoadFailed(errorDrawable: Drawable?) {
                    listener.onBitmapError()
                }

                override fun onResourceReady(
                    bitmap: Bitmap,
                    transition: Transition<in Bitmap>?
                ) {
                    listener.onBitmapSuccess(bitmap)
                }
            })
    }

    private fun glideLoad(glideReq: RequestManager, options: RequestOptions, imageView: ImageView) {
        when {
            !TextUtils.isEmpty(mUrl) -> {
                glideReq.load(mUrl)
            }
            mResId != 0 -> {
                glideReq.load(mResId)
            }
            else -> {
                XLog.e("ImgLoader : img url and resId is null")
                imageView.setImageDrawable(mPreDrawable)
                return
            }
        }.apply(options)
            .into(imageView)
    }

    private fun foundOptions(format: ImgFormat, scaleType: ImgScaleType): RequestOptions {
        val scaleMode = ImgScaleTypeFactory.foundScaleMode(scaleType)
        return ImgFormatFactory.foundOptionByFormatAndScale(format, scaleMode)
    }

}